<?php
/**
 * Wechat relation
 *
 * @author Dr.dragon
 *
 */

namespace dragon\Support;

use dragon\Exceptions\WechatException;
use dragon\Exceptions\TaskException;
use dragon\User\User;
use dragon\Wechat\Wechat as WechatSDK;
use dragon\Wechat\WechatRequest;
use think\Db;
use think\Config;
use think\Exception;

class Wechat
{
    protected static $instances;

    public static function instance($key)
    {
        if (isset(static::$instances[$key])) return static::$instances[$key];

        switch ($key) {
            case 'sdk':
                $config = config('wechat.' . config('wechat_account'));
                /* 加载微信SDK */
                $options = array(
                    'token' => $config['wechat_token'],             //填写你设定的key
                    'encodingaeskey' => $config['wechat_encodingaeskey'],   //填写加密用的EncodingAESKey，如接口为明文模式可忽略
                    'appid' => $config['wechat_appid'],            //填写高级调用功能的app id
                    'appsecret' => $config['wechat_appsecret']            //填写高级调用功能的密钥
                );
                $instance = new WechatSDK($options);
                break;
            case 'sence':
                $instance = Db::name('wechat_sence');
                break;
        }
        return static::$instances[$key] = $instance;
    }

    public static function sdk()
    {
        return static::instance('sdk');
    }

    // create sence: 场景指向 class & actoin & 附带参数
    public static function getSence($class, $taskname, $params, $type = 0)
    {
        $task = $class::{'get' . ucfirst($taskname)}($params);

        $sence = array(
            'scene_type' => $type,
            'class' => $class,
            'task_name' => $taskname,
            'task_id' => $task['id'],
            'timestamp' => time(),
        );

        $task['sence_id'] = static::instance('sence')->insertGetId($sence);

        // type = 1 永久二维码
        $qrcode = static::instance('sdk')->getQRCode($task['sence_id'], $type);
        $task['qrcode'] = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=' . $qrcode['ticket'];

        static::instance('sence')->where(array('id' => $task['sence_id']))->update(array('qrcode' => $task['qrcode']));

        return $task;
    }

    // create sence: 场景指向 class & actoin & 附带参数
    public static function getLimitSence($class, $taskname, $params)
    {
        return static::getSence($class, $taskname, $params, 1);
    }

    protected static function make($class)
    {
        return new $class();
    }

    // do sence
    public static function doSence($id)
    {
        $wechat = static::instance('sdk');
        $sence = static::instance('sence')->where('id', $id)->find();
        if (!$sence || $sence['status']) throw new TaskException('任务不存在或已执行', 50001);    // 任务不存在或已执行

        return static::make($sence['class'])->{'do' . ucfirst($sence['task_name'])}($wechat, $sence['task_id']);
    }

    public static function receive()
    {
        $data = array(
            'get' => http_build_query($_GET),
            'post' => http_build_query($_POST),
            'input' => file_get_contents("php://input"),
            'create_time' => date('Y-m-d H:i:s'),
        );
        $log = new WechatRequest($data);
        $log->save();

        try {
            $wechat = static::instance('sdk');
            $wechat->valid(); //明文或兼容模式可以在接口验证通过后注释此句，但加密模式一定不能注释，否则会验证失败
            $wechat->log = $log;
            $type = $wechat->getRev()->getRevType();
            switch ($type) {
                case WechatSDK::MSGTYPE_TEXT:
                    $text = $wechat->getRev()->getRevContent();
                    static::receiveText(trim($text));
                    break;
                case WechatSDK::MSGTYPE_EVENT:
                    $event = $wechat->getRev()->getRevEvent();
                    static::receiveEvent($event);
                    break;
                case WechatSDK::MSGTYPE_IMAGE:
                    break;
                case WechatSDK::MSGTYPE_VOICE:
                    $contentStr = "感谢您的互动。语音识别对我来说有点困难。若不能及时回应您的信息，请谅解。\n";
                    $wechat->text($contentStr)->reply();
                    break;
                default:
                    $contentStr = "智慧溧水感谢您的关注！\n";
                    $wechat->text($contentStr)->reply();
            }
        } catch (Exception $e) {
            $log->response = $e->getMessage()."\r\n".$e->getTraceAsString();
            $log->save();
        }
    }

    private function logdebug($text)
    {
        return file_put_contents(dirname(__FILE__) . '\log.txt', $text . "\n", FILE_APPEND);
    }

    private static function receiveEvent($event)
    {
        $contentStr = "";
        $wechat = static::instance('sdk');
        switch ($event['event']) {
            case WechatSDK::EVENT_SUBSCRIBE:
                $code = $wechat->getRevSceneId(); // 二维码参数
                if ($code) static::scanCode($code);

                $contentStr = "感谢您关注！\n";
                $wechat->text($contentStr)->reply();
                break;
            case WechatSDK::EVENT_UNSUBSCRIBE:
                break;
            case WechatSDK::EVENT_MENU_VIEW:
                break;
            case WechatSDK::EVENT_MENU_CLICK:
                break;
            case WechatSDK::EVENT_SCAN:                    // 二维码
                static::scanCode($event['key']);
                break;
        }
    }

    // 二维码扫描结果 在这里 code 场景ID
    private static function scanCode($code)
    {
        $wechat = static::instance('sdk');
        $sence = static::instance('sence')->where('id', $code)->find();

        if (!$sence) return $wechat->text("数据无效或已过期！\n")->reply();

        try {
            static::make($sence['class'])->{'do' . ucfirst($sence['task_name'])}($wechat, $sence['task_id']);
        } catch (WechatException $e) {
            $contentStr = 'Error: ' . $e->getMessage();
            $wechat->text($contentStr)->reply();
        } catch (TaskException $e) {
            $contentStr = 'Error: ' . $e->getMessage();
            $wechat->text($contentStr)->reply();
        }
    }

    private static function receiveText($text)
    {
    }


    /**
     * 发送模板消息
     *
     * @param       $user
     * @param array $data 消息结构
     *                    ｛
     *                    "touser":"OPENID",
     *                    "template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY",
     *                    "url":"http://weixin.qq.com/download",
     *                    "topcolor":"#FF0000",
     *                    "data":{
     *                    "参数名1": {
     *                    "value":"参数",
     *                    "color":"#173177"     //参数颜色
     *                    },
     *                    "Date":{
     *                    "value":"06月07日 19时24分",
     *                    "color":"#173177"
     *                    },
     *                    "CardNumber":{
     *                    "value":"0426",
     *                    "color":"#173177"
     *                    },
     *                    "Type":{
     *                    "value":"消费",
     *                    "color":"#173177"
     *                    }
     *                    }
     *                    }
     *
     * @return boolean|array
     */
    public static function notify($user, $data, $temp = 'mRvFAHd8tc21LMH5P3IK6EyD1ork-5XRNsYC5GENFRc')
    {
        $wechat = static::instance('sdk');
        is_numeric($user) and $user = User::get($user);
        foreach ($data as $k => $v) {
            $data[$k] = array(
                'value' => $v,
                'color' => '#173177',
            );
        }
        $data = array(
            'touser' => $user['openid'],
            'template_id' => $temp,
            'url' => $data['value']['url'],
            'topcolor' => '#ff0000',
            'data' => $data,
        );

        return $wechat->sendTemplateMessage($data);
    }


    // 微信菜单推送
    public static function menuPush()
    {
        $account = config('wechat_account');
        $list = Db::name('wechat_menu')->where('account', $account)->select();
        $menus = [];
        foreach ($list as $key => $val) {
            if ($val['parent_id']) continue;

            // 顶级菜单
            $menu = [];
            $menu['name'] = $val['name'];
            if ($val['type']) {
                $menu['type'] = $val['type'];
                if (strtoupper($val['type']) == WechatSDK::EVENT_MENU_VIEW) {
                    $menu['url'] = $val['url'];
                } else {
                    $menu['key'] = $val['key'];
                }
            }

            // 子菜单
            foreach ($list as $k => $v) {
                $subMenu = [];
                if ($v['parent_id'] == $val['id']) {
                    $subMenu['name'] = $v['name'];
                    $subMenu['type'] = $v['type'];
                    if (strtoupper($subMenu['type']) == WechatSDK::EVENT_MENU_VIEW) {
                        $subMenu['url'] = $v['url'];
                    } else {
                        $subMenu['key'] = $v['key'];
                    }
                    $menu['sub_button'][] = $subMenu;
                }
            }
            $menus['button'][] = $menu;
        }
        // 提交菜单
        return static::instance('sdk')->createMenu($menus);
    }

    // 获取wechat账号
    public static function getWechetAccount()
    {
        $wechet = config('wechat');
        $list = [];
        foreach ($wechet as $k => $v) {
            $list[$k] = $k;
        }

        return $list;
    }

}

















